/******************************************************************************* * Copyright (c) 2004, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.tools.internal; import java.io.*; import java.lang.reflect.*; import java.util.*; import org.eclipse.jdt.core.dom.*; import org.eclipse.jdt.core.dom.Modifier; public class ReflectMethod extends ReflectItem implements JNIMethod { Method method; ReflectType returnType, returnType64; ReflectType[] paramTypes, paramTypes64; ReflectClass declaringClass; Boolean unique; public ReflectMethod(ReflectClass declaringClass, Method method, String source, CompilationUnit unit) { this.method = method; this.declaringClass = declaringClass; Class<?> returnType = method.getReturnType(); Class<?>[] paramTypes = method.getParameterTypes(); this.returnType = new ReflectType(returnType); this.returnType64 = this.returnType; this.paramTypes = new ReflectType[paramTypes.length]; this.paramTypes64 = new ReflectType[paramTypes.length]; for (int i = 0; i < this.paramTypes.length; i++) { this.paramTypes[i] = this.paramTypes64[i] = new ReflectType(paramTypes[i]); } boolean changes = false; if ((method.getModifiers() & Modifier.NATIVE) != 0) { changes = canChange64(returnType); if (!changes) { for (int i = 0; i < paramTypes.length && !changes; i++) { changes |= canChange64(paramTypes[i]); } } } if (changes && new File(declaringClass.sourcePath).exists()) { String name = method.getName(); TypeDeclaration type = (TypeDeclaration)unit.types().get(0); MethodDeclaration decl = null; MethodDeclaration[] methods = type.getMethods(); for (int i = 0; i < methods.length && decl == null; i++) { MethodDeclaration node = methods[i]; if (node.getName().getIdentifier().equals(name)) { if (!declaringClass.getSimpleName(returnType).equals(node.getReturnType2().toString())) continue; List<?> parameters = node.parameters(); if (parameters.size() != paramTypes.length) continue; decl = node; for (int j = 0; j < paramTypes.length; j++) { if (!declaringClass.getSimpleName(paramTypes[j]).equals(((SingleVariableDeclaration)parameters.get(j)).getType().toString())) { decl = null; break; } } } } for (int i = 0; i < paramTypes.length; i++) { if (canChange64(paramTypes[i])) { Class<?> clazz = paramTypes[i]; SingleVariableDeclaration node = (SingleVariableDeclaration)decl.parameters().get(i); String s = source.substring(node.getStartPosition(), node.getStartPosition() + node.getLength()); if (clazz == int.class && s.indexOf("int /*long*/") != -1) this.paramTypes64[i] = new ReflectType(long.class); else if (clazz == int[].class && (s.indexOf("int /*long*/") != -1 || s.indexOf("int[] /*long[]*/") != -1)) this.paramTypes64[i] = new ReflectType(long[].class); else if (clazz == float.class && s.indexOf("float /*double*/") != -1) this.paramTypes64[i] = new ReflectType(double.class); else if (clazz == float[].class && (s.indexOf("float /*double*/") != -1|| s.indexOf("float[] /*double[]*/") != -1)) this.paramTypes64[i] = new ReflectType(double[].class); else if (clazz == long.class && s.indexOf("long /*int*/") != -1) this.paramTypes[i] = new ReflectType(int.class); else if (clazz == long[].class && (s.indexOf("long /*int*/") != -1|| s.indexOf("long[] /*int[]*/") != -1)) this.paramTypes[i] = new ReflectType(int[].class); else if (clazz == double.class && s.indexOf("double /*float*/") != -1) this.paramTypes[i] = new ReflectType(float.class); else if (clazz == double[].class && (s.indexOf("double /*float*/") != -1|| s.indexOf("double[] /*float[]*/") != -1)) this.paramTypes[i] = new ReflectType(float[].class); } } if (canChange64(returnType)) { Class<?> clazz = returnType; ASTNode node = decl.getReturnType2(); String s = source.substring(node.getStartPosition(), decl.getName().getStartPosition()); if (clazz == int.class && s.indexOf("int /*long*/") != -1) this.returnType64 = new ReflectType(long.class); else if (clazz == int[].class && (s.indexOf("int /*long*/") != -1 || s.indexOf("int[] /*long[]*/") != -1)) this.returnType64 = new ReflectType(long[].class); else if (clazz == float.class && s.indexOf("float /*double*/") != -1) this.returnType64 = new ReflectType(double.class); else if (clazz == float[].class && (s.indexOf("float /*double*/") != -1|| s.indexOf("float[] /*double[]*/") != -1)) this.returnType64 = new ReflectType(double[].class); else if (clazz == long.class && s.indexOf("long /*int*/") != -1) this.returnType = new ReflectType(int.class); else if (clazz == long[].class && (s.indexOf("long /*int*/") != -1|| s.indexOf("long[] /*int[]*/") != -1)) this.returnType = new ReflectType(int[].class); else if (clazz == double.class && s.indexOf("double /*float*/") != -1) this.returnType = new ReflectType(float.class); else if (clazz == double[].class && (s.indexOf("double /*float*/") != -1|| s.indexOf("double[] /*float[]*/") != -1)) this.returnType = new ReflectType(float[].class); } } } @Override public int hashCode() { return method.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof ReflectMethod)) return false; return ((ReflectMethod)obj).method.equals(method); } @Override public JNIClass getDeclaringClass() { return declaringClass; } @Override public int getModifiers() { return method.getModifiers(); } @Override public String getName() { return method.getName(); } @Override public boolean isNativeUnique() { if (unique != null) return unique.booleanValue(); boolean result = true; String name = getName(); JNIMethod[] methods = declaringClass.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { JNIMethod mth = methods[i]; if ((mth.getModifiers() & Modifier.NATIVE) != 0 && this != mth && !this.equals(mth) && name.equals(mth.getName())) { result = false; break; } } unique = Boolean.valueOf(result); return result; } @Override public JNIType[] getParameterTypes() { return paramTypes; } @Override public JNIType[] getParameterTypes64() { return paramTypes64; } @Override public JNIParameter[] getParameters() { Class<?>[] paramTypes = method.getParameterTypes(); ReflectParameter[] result = new ReflectParameter[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { result[i] = new ReflectParameter(this, i); } return result; } @Override public JNIType getReturnType() { return returnType; } @Override public JNIType getReturnType64() { return returnType64; } @Override public String getAccessor() { return (String)getParam("accessor"); } @Override public String getExclude() { return (String)getParam("exclude"); } @Override public String getMetaData() { String className = getDeclaringClass().getSimpleName(); String key = className + "_" + JNIGenerator.getFunctionName(this); MetaData metaData = declaringClass.metaData; String value = metaData.getMetaData(key, null); if (value == null) { key = className + "_" + method.getName(); value = metaData.getMetaData(key, null); } /* * Support for 64 bit port. */ if (value == null) { JNIType[] paramTypes = getParameterTypes(); if (convertTo32Bit(paramTypes, true)) { key = className + "_" + JNIGenerator.getFunctionName(this, paramTypes); value = metaData.getMetaData(key, null); } if (value == null) { paramTypes = getParameterTypes(); if (convertTo32Bit(paramTypes, false)) { key = className + "_" + JNIGenerator.getFunctionName(this, paramTypes); value = metaData.getMetaData(key, null); } } } /* * Support for lock. */ if (value == null && method.getName().startsWith("_")) { key = className + "_" + JNIGenerator.getFunctionName(this).substring(2); value = metaData.getMetaData(key, null); if (value == null) { key = className + "_" + method.getName().substring(1); value = metaData.getMetaData(key, null); } } if (value == null) value = ""; return value; } @Override public void setAccessor(String str) { setParam("accessor", str); } @Override public void setExclude(String str) { setParam("exclude", str); } @Override public void setMetaData(String value) { String key; String className = declaringClass.getSimpleName(); if (isNativeUnique()) { key = className + "_" + method.getName (); } else { key = className + "_" + JNIGenerator.getFunctionName(this); } declaringClass.metaData.setMetaData(key, value); } @Override public String toString() { return method.toString(); } }